// 全局变量, 里面的属性就是约定好的, 用来表示游戏的初始信息
gameInfo = {
    roomId: null,
    selfPlayerId: null,
    antiPlayerId: null,
    isWhite: true,
}

// 初始化 websocket, 使客户端能够连上服务器的游戏房间
// 注意这里的路径要写成 /game, 不是 /game/
let webSocketUrl = "ws://" + location.host + "/game"
let websocket = new WebSocket(webSocketUrl);

websocket.onopen = function () {
    console.log("连接服务器游戏房间成功")
}

websocket.onclose = function () {
    console.log("和游戏服务器断开连接")
}

websocket.onerror = function () {
    console.log("和服务器连接出现异常")
}

// 监听浏览器是否关闭, 如果用户手动关闭浏览器标签, 那么就主动断开连接
window.onbeforeunload = function () {
    websocket.close()
}

// 这个方法是用来处理: 服务器返回的响应
websocket.onmessage = function (event) {
    console.log("处理服务器返回的响应: " + event.data);
    // 这里的响应 event 是一个 JSON 字符串, 属于是 Java 的对象, 需要转成 js 对象
    // event.data 拿到的就是 JSON 字符串这个对象
    let response = JSON.parse(event.data);

    if (response.message != 'readyToGame') {
        // 根据约定, 如果服务器没有返回对应的信息, 说明出现了bug
        console.log("响应类型出错, 没有返回应有的信息.");
        alert("连接异常,请重新登录");
        location.replace("login.html");
        return;
    }

    if (!response.success) {
        alert("连接游戏失败, reason: " + response.reason);
        // 回到游戏大厅
        location.replace("/game_hall.html");
    }

    // 走到这里说明匹配成功, 准备玩家信息, 然后开始游戏
    gameInfo.roomId = response.roomId;
    gameInfo.selfPlayerId = response.selfPlayerId;
    gameInfo.antiPlayerId = response.antiPlayerId;
    gameInfo.isWhite = (response.whiteUser == response.selfPlayerId);

    // 初始化棋盘(应该在所有信息都准备好的时候, 才开始出现棋盘, 然后开始游戏)
    initGame();

    // 修改 "等待玩家连接中" 的样式(准备开始游戏后, 游戏房间下面的字样应该改成由谁落子)
    setScreenText(gameInfo.isWhite);
}

// 设定界面相关操作
// 这个方法来切换落子显示
function setScreenText(me) {
    let screen = document.querySelector('#screen');
    if (me) {
        screen.innerHTML = "轮到你落子了.";
    }else {
        screen.innerHTML = "轮到对方落子了.";
    }
}

// 初始化一局游戏
function initGame() {
    // 该谁下棋, 是根据服务器分配情况来决定,
    // me 为 true, 轮到 "我" 落子
    // me 为 false, 轮到 "对方" 落子
    let me = gameInfo.isWhite;

    // 游戏是否结束
    let isOver = false;

    // chessBoard 是一个二维数组, 用来表示棋盘
    // 构造这个数组的目的是为了, 防止重复落子, 落子前需要判定该位置是否已经有棋子了
    let chessBoard = [];
    for (let i = 0; i < 15; i++) {
        // 棋盘是 15*15 的布局
        // chessBoard[i] = []. 表示该数组的每个元素, 又是一个数组
        chessBoard[i] = [];
        for (let j = 0; j < 15; j++) {
            // 0 表示该位置是空的, 非0 表示该位置已经有棋子了
            chessBoard[i][j] = 0;
        }
    }

    // 获取 chess 标签
    let chess = document.querySelector('#chess');

    // 这后面就是 canvas API 了
    let context = chess.getContext("2d");
    context.strokeStyle = "#BFBFBF";
    // 背景图片
    let logo = new Image();
    logo.src = "pic/boardBackground.png";
    logo.onload = function () {
        console.log("绘制棋盘")

        context.drawImage(logo, 0, 0, 450, 450);
        initChessBoard();
    }


    // 绘制棋盘网格
    function initChessBoard() {
        for (let i = 0; i < 15; i++) {
            context.moveTo(15 + i * 30, 15);
            context.lineTo(15 + i * 30, 430);
            context.stroke();
            context.moveTo(15, 15 + i * 30);
            context.lineTo(435, 15 + i * 30);
            context.stroke();
        }
    }

    // 绘制一个棋子, me 为 true
    function oneStep(col, row, isWhite) {
        context.beginPath();
        context.arc(15 + col * 30, 15 + row * 30, 13, 0, 2 * Math.PI);
        context.closePath();
        var gradient = context.createRadialGradient(15 + col * 30 + 2, 15 + row * 30 - 2, 13, 15 + col * 30 + 2, 15 + row * 30 - 2, 0);
        if (!isWhite) {
            // isWhite : true 表示下白子, false 表示下黑子
            gradient.addColorStop(0, "#0A0A0A");
            gradient.addColorStop(1, "#636766");
        } else {
            gradient.addColorStop(0, "#D1D1D1");
            gradient.addColorStop(1, "#F9F9F9");
        }
        context.fillStyle = gradient;
        context.fill();
    }

    // 点击事件, 针对棋盘有一个点击回调, 即 下棋
    chess.onclick = function (e) {
        if (isOver) {
            return;
        }
        if (!me) {
            // 如果该轮回合不论到 "我" 那么点击也没有用
            return;
        }
        let x = e.offsetX;
        let y = e.offsetY;
        // 注意, 横坐标是列, 纵坐标是行
        let col = Math.floor(x / 30);
        let row = Math.floor(y / 30);
        if (chessBoard[row][col] == 0) {
            // 发送坐标给服务器, 服务器要返回结果
            send(row, col);

            // 留到浏览器收到落子响应的时候再处理(收到响应再来画棋子)
            // oneStep: 点击就可以在对应坐标上绘制棋子
            //oneStep(col, row, gameInfo.isWhite);
            // 落子后, 将棋子坐标的值更改为1, 表示这个位置已经有棋子了
            //chessBoard[row][col] = 1;
        }
    }

    function send(row, col) {
        // 根据之前约定好的接口标准进行发送
        let request = {
            message: 'putChess',
            userId: gameInfo.selfPlayerId,
            row: row,
            col: col
        };

        // 因为发送的数据是以 json 格式发送, 且这里是 JS 对象, 所以需要将数据从 JS对象 转成 JSON 字符串
        websocket.send(JSON.stringify(request));
    }

    // 在 initGame() 之外的 websocket.onmessage 是用来处理游戏就绪的响应, 主要用于初始化, 初始化完毕后就不再调用
    // 而现在期望前端能够处理 "落子" 响应, 那么就可以在 initGame() 内部再构造一个 websocket.onmessage
    websocket.onmessage = function (event) {
        console.log("处理落子响应, 接收数据: " + event.data);

        // 将 Java对象 转换成 JS对象
        let response = JSON.parse(event.data);
        if (response.message != 'putChess') {
            console.log("putChess响应类型错误");
            return;
        }

        // 响应类型正确, 则需要绘制棋子了
        // 判定这次响应是谁来绘制棋子
        if (response.userId == gameInfo.selfPlayerId) {
            // 如果响应里面的落子玩家是 "我", 那么 "我" 来绘制棋子
            // 通过 oneStep() 来绘制棋子
            oneStep(response.col, response.row, gameInfo.isWhite);
        }else if (response.userId == gameInfo.antiPlayerId) {
            // 响应里面的落子玩家是 "对手", 那么就由 "对手" 来绘制
            // 注意第三个参数, 如果 "我" 是白方, 那么 "对手" 就应该是黑方, 如果 "我" 是黑方, 那么 "对手" 就是白方.
            // 这需要加上 ! 运算
            oneStep(response.col, response.row, !gameInfo.isWhite);
        }else {
            // 响应出错, 有未知 userId
            console.log("未知userId: " + response.userId);
            return;
        }

        // 给所下棋的坐标位置设置为1
        chessBoard[response.row][response.col] = 1;

        // 交换双方回合
        // 由该 "我" 下棋, 变为不是 "我" 下棋, 也就是该 "对方" 下棋
        // 所以 me 要改成 !me
        me = !me;
        setScreenText(me);

        // 判定游戏是否结束
        // 选取游戏下方提示区域
        let screenDiv = document.querySelector('#screen');
        let winner = response.winner;
        if (winner != 0) {
            if (winner == gameInfo.selfPlayerId) {
                // 如果赢家id 等于 "我"的id, 说明 "我" 赢了
                screenDiv.innerHTML = '你赢了!';
                //alert("你赢了!");
            }else if (winner == gameInfo.antiPlayerId) {
                // 如果赢家id 等于 "对手"id, 说明 "我" 输了
                screenDiv.innerHTML = '你输了!';
                //alert("你输了!");
            }else {
                alert("未知winnerId: " + winner);
            }

            // 回到游戏大厅
            // location.replace("game_hall.html");

            // 增加一个 "返回大厅" 按钮, 让玩家来手动决定回到游戏大厅
            let backButton = document.createElement('button');
            backButton.innerHTML = '回到大厅';
            backButton.onclick = function () {
                location.replace("/game_hall.html");
            }

            let fatherDiv = document.querySelector('.container>div');
            fatherDiv.appendChild(backButton);

        }
    }
}

